#!/usr/bin/env bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

function HELP {
    echo "help:"
    echo "-b a virtio block device"
    echo "-c cmpctmalloc instead of dlmalloc"
    echo "-M miniheap instead of dlmalloc"
    echo "-n a virtio network device"
    echo "-t a virtio tap network device"
    echo "-d a virtio display"
    echo "-3 cortex-m3 based platform"
    echo "-6 64bit arm"
    echo "-m <memory in MB>"
    echo "-s <number of cpus>"
    echo "-h for help"
    echo "all arguments after -- are passed to qemu directly"
    exit 1
}

DO_NET=0
DO_NET_TAP=0
DO_BLOCK=0
DO_64BIT=0
DO_CORTEX_M3=0
DO_DISPLAY=0
DO_CMPCTMALLOC=0
DO_MINIHEAP=0
SMP=1
MEMSIZE=512
SUDO=""
PROJECT=""

while getopts bdhm:cMnt36p:s: FLAG; do
    case $FLAG in
        b) DO_BLOCK=1;;
        c) DO_CMPCTMALLOC=1;;
        d) DO_DISPLAY=1;;
        M) DO_MINIHEAP=1;;
        n) DO_NET=1;;
        t) DO_NET_TAP=1;;
        3) DO_CORTEX_M3=1;;
        6) DO_64BIT=1;;
        m) MEMSIZE=$OPTARG;;
        s) SMP=$OPTARG;;
        p) PROJECT=$OPTARG;;
        h) HELP;;
        \?)
            echo unrecognized option
            HELP
    esac
done

shift $((OPTIND-1))

if [ $DO_64BIT == 1 ]; then
    QEMU="qemu-system-aarch64"
    CPU="cortex-a53"
    MACHINE="virt"
    _PROJECT="qemu-virt-arm64-test"
elif [ $DO_CORTEX_M3 == 1 ]; then
    QEMU="qemu-system-arm"
    CPU="cortex-m3"
    MACHINE="lm3s6965evb"
    _PROJECT="lm3s6965evb-test"
else
    QEMU="qemu-system-arm"
    CPU="cortex-a15"
    MACHINE="virt"
    _PROJECT="qemu-virt-arm32-test"
fi
if [ "$PROJECT" == "" ]; then
    PROJECT=$_PROJECT
fi

ARGS=" -cpu $CPU -m $MEMSIZE -smp $SMP -machine $MACHINE -kernel build-${PROJECT}/lk.elf"
BLOCK_ARGS=" -drive if=none,file=blk.bin,id=blk,format=raw -device virtio-blk-device,drive=blk"
NET_ARGS=" -netdev user,id=vmnic,hostname=qemu -device virtio-net-device,netdev=vmnic"
NET_TAP_ARGS=" -netdev tap,id=vmnic -device virtio-net-device,netdev=vmnic"
NO_DISPLAY_ARGS=" -nographic"
DISPLAY_ARGS=" -device virtio-gpu-device -serial stdio"

echo DO_BLOCK = $DO_BLOCK
echo DO_NET = $DO_NET

if [ $DO_BLOCK == 1 ]; then
    ARGS+=$BLOCK_ARGS
fi
if [ $DO_NET == 1 ]; then
    ARGS+=$NET_ARGS
fi
if [ $DO_NET_TAP == 1 ]; then
    ARGS+=$NET_TAP_ARGS
    SUDO="sudo "
fi
if [ $DO_DISPLAY == 1 ]; then
    ARGS+=$DISPLAY_ARGS
else
    ARGS+=$NO_DISPLAY_ARGS
fi

MAKE_VARS=""

if [ $DO_CMPCTMALLOC == 1 ]; then
    MAKE_VARS=LK_HEAP_IMPLEMENTATION=cmpctmalloc
elif [ $DO_MINIHEAP == 1 ]; then
    MAKE_VARS=LK_HEAP_IMPLEMENTATION=miniheap
fi

$DIR/make-parallel $MAKE_VARS $PROJECT &&
echo $SUDO $QEMU $ARGS $@ &&
$SUDO $QEMU $ARGS $@
